﻿using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Linq.Expressions;
using SqlSugar.Extensions;
using HBKY.Shop.IRepository.Base;
using HBKY.Shop.Common.RequestAccessor;
using HBKY.Shop.IRepository;
using HBKY.Shop.Common.Helper;
using HBKY.Shop.Common.DB;
namespace HBKY.Shop.Repository.Base
{
    public class Repository<TEntity> : IRepository<TEntity>  where TEntity : class, new()
    {
        private SqlSugarClient _dbBase;

        /// <summary>
        /// 当前操作人
        /// </summary>
        public ICurrentUser _currentUser { protected get; set; }

        public ISugarQueryable<TEntity> Queryable => _db.Queryable<TEntity>();

        public ISqlSugarClient Db => _db;

        /// <summary>
        /// 综合查询平台构造函数
        /// </summary>
        /// <param name="unitOfWork"></param>
        public Repository(IUnitOfWork unitOfWork)
        {
            _dbBase = unitOfWork.GetDbClient();
        }

        #region 根据不同操作切换对应的sql

        internal ISqlSugarClient _db
        {
            get
            {
                /* 如果要开启多库支持，
                 * 1、在appsettings.json 中开启MutiDBEnabled节点为true，必填
                 * 2、设置一个主连接的数据库ID，节点MainDB，对应的连接字符串的Enabled也必须true，必填
                 */
                if (Appsettings.Option("MutiDBEnabled").ObjToBool())
                {
                    if (typeof(TEntity).GetTypeInfo().GetCustomAttributes(typeof(SugarTable), true)
                            .FirstOrDefault((x => x.GetType() == typeof(SugarTable))) is SugarTable sugarTable &&
                        !string.IsNullOrEmpty(sugarTable.TableDescription))
                    {
                        _dbBase.ChangeDatabase(sugarTable.TableDescription.ToLower());
                    }
                    else
                    {
                        _dbBase.ChangeDatabase(MainDb.CurrentDbConnId.ToLower());
                    }
                }

                return _dbBase;
            }
        }

        #endregion

        #region 事务管理器

        public void BeginTran()
        {
            _db.Ado.BeginTran();
        }

        public void Commit()
        {
            _db.Ado.CommitTran();
        }

        public void Rollback()
        {
            _db.Ado.RollbackTran();
        }

        #endregion

        /// <summary>
        /// 功能描述:根据ID查询数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<TEntity> GetById(int id)
        {
            return await _db.Queryable<TEntity>().InSingleAsync(id);
        }

        /// <summary>
        /// 功能描述:根据ID列表查询数据
        /// </summary>
        /// <param name="ids">id列表</param>
        /// <returns>数据实体列表</returns>
        public async Task<List<TEntity>> GetListByIds(IEnumerable<int> ids)
        {
            return await _db.Queryable<TEntity>().In(ids).ToListAsync();
        }

        /// <summary>
        /// 功能描述:查询所有数据
        /// </summary>
        /// <returns>数据列表</returns>
        public async Task<List<TEntity>> GetList()
        {
            return await _db.Queryable<TEntity>().ToListAsync();
        }

        /// <summary>
        /// 新增修改数据
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<bool> Save(TEntity entity)
        {
            return await _db.Saveable(entity).ExecuteCommandAsync() > 0;
        }

        public async Task<bool> Add(TEntity entity)
        {
            return await _db.Insertable(entity).ExecuteCommandAsync() > 0;
        }

        public async Task<TEntity> AddReturnEntity(TEntity entity)
        {
            return await _db.Insertable(entity).ExecuteReturnEntityAsync();
        }

        /// <summary>
        /// 写入实体数据
        /// </summary>
        /// <param name="entity"></param>
        /// <returns>数据ID</returns>
        public async Task<int> AddReutrnIdentity(TEntity entity)
        {
            return await _db.Insertable(entity).ExecuteReturnIdentityAsync();
        }

        /// <summary>
        /// 批量插入实体(速度快)
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <returns>影响行数</returns>
        public async Task<int> AddBatch(List<TEntity> entities)
        {
            return await _db.Insertable(entities).ExecuteCommandAsync();
        }

        /// <summary>
        /// 更新实体数据
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<bool> Update(TEntity entity)
        {
            return await _db.Updateable(entity).ExecuteCommandHasChangeAsync();
        }

        /// <summary>
        /// 指定字段更新 传入字段委托
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="columns"></param>
        /// <returns></returns>
        public async Task<bool> Update(TEntity entity, Expression<Func<TEntity, object>> columns)
        {
            return await _db.Updateable(entity).UpdateColumns(columns)
                .ExecuteCommandHasChangeAsync();
        }


        /// <summary>
        /// 指定字段更新 传入字段委托
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="columns"></param>
        /// <returns></returns>
        public async Task<bool> UpdateBatch(List<TEntity> entity, Expression<Func<TEntity, object>> columns)
        {
            return await _db.Updateable(entity).UpdateColumns(columns)
                .ExecuteCommandHasChangeAsync();
        }

        /// <summary>
        /// 根据id 修改指定字段
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="columns"></param>
        /// <returns></returns>
        public async Task<bool> Update(object id, Expression<Func<TEntity, object>> columns,
            Expression<Func<TEntity, bool>> setValueExpression)
        {
            return await _db.Updateable<TEntity>().Where($"Id ={id}")//.Where(o => o.Id == id)
                .ReSetValue(setValueExpression)
                .WhereColumns(columns)
                .ExecuteCommandHasChangeAsync();
        }

        /// <summary>
        /// 指定字段更新 传入字段数组
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="columns"></param>
        /// <returns></returns>
        public async Task<bool> Update(TEntity entity, params string[] columns)
        {
            return await _db.Updateable(entity).UpdateColumns(columns)
                .ExecuteCommandHasChangeAsync();
        }

        /// <summary>
        /// 更新实体列表数据
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public async Task<bool> UpdateBatch(List<TEntity> entities)
        {
            return await _db.Updateable(entities).ExecuteCommandHasChangeAsync();
        }

        /// <summary>
        /// 实体没有配置主键或者不想用主键作为条件 ,我们能过WhereColumns设置条件字段
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="columns"></param>
        /// <returns></returns>
        public async Task<bool> UpdateBatchFilterExist(List<TEntity> entity, Expression<Func<TEntity, object>> columns)
        {
            var result = _db.Storageable(entity).Saveable()
                    .WhereColumns(columns).ToStorage();
            await  result.AsInsertable.ExecuteCommandAsync(); //执行插入
            await  result.AsUpdateable.ExecuteCommandAsync(); //执行更新
            return true;
        }

        /// <summary>
        /// 批量根据修改指定字段
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="columns"></param>
        /// <returns></returns>
        public async Task<bool> UpdateBatch(IEnumerable<int> ids, Expression<Func<TEntity, TEntity>> columns)
        {
            return await _db.Updateable<TEntity>().Where($"Id IN ({string.Join(',', ids)})")//.Where(o => ids.Contains(o.Id))
                .SetColumns(columns)
                .ExecuteCommandHasChangeAsync();
        }

        public ISugarQueryable<TEntity> Where(Expression<Func<TEntity, bool>> expression)
        {
            return _db.Queryable<TEntity>().Where(expression);
        }

        public ISugarQueryable<TEntity> WhereIF(bool isWhere, Expression<Func<TEntity, bool>> expression)
        {
            return _db.Queryable<TEntity>().WhereIF(isWhere, expression);
        }

        /// <summary>
        /// 根据实体删除一条数据 -软删除
        /// </summary>
        /// <returns></returns>
        public async Task<bool> Delete(TEntity entity)
        {
            return await _db.Deleteable(entity).ExecuteCommandHasChangeAsync();
        }

        /// <summary>
        /// 删除指定ID的数据 -软删除
        /// </summary>
        /// <param name="id">主键ID</param>
        /// <returns></returns>
        public async Task<bool> DeleteById(dynamic id)
        {
            return await _db.Deleteable<TEntity>(id).ExecuteCommandHasChangeAsync();
        }

        /// <summary>
        /// 删除指定ID集合的数据(批量删除) -软删除
        /// </summary>
        /// <param name="ids">主键ID集合</param>
        /// <returns></returns>
        public async Task<bool> DeleteByIds(List<dynamic> ids)
        {
            return await _db.Deleteable<TEntity>().In(ids).ExecuteCommandHasChangeAsync();
        }


        /// <summary>
        /// 根据表达式删除数据
        /// </summary>
        /// <returns></returns>
        public async Task<bool> Delete(Expression<Func<TEntity, bool>> expression)
        {
            return await _db.Deleteable(expression).ExecuteCommandHasChangeAsync();
        }
    }
}